summaryrefslogtreecommitdiff
path: root/app/[lng]
diff options
context:
space:
mode:
Diffstat (limited to 'app/[lng]')
-rw-r--r--app/[lng]/evcp/(evcp)/(eng)/cover/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(eng)/document-list-ship/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(eng)/vendor-data/layout.tsx11
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/buyer-signature/page.tsx2
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/esg-check-list/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/evaluation-check-list/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/evaluation-target-list/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/general-contract-template/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/material-groups/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/p-items/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/payment-conditions/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/pq-criteria/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(master-data)/vendor-check-list/page.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/avl/avl-page-client.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/basic-contract/page.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/bid-failure/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/bid-receive/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/bid-selection/page.tsx15
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/bid/page.tsx4
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/evaluation-input/page.tsx12
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/evaluation/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/general-contracts/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/itb-create/page.tsx15
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/pcr/page.tsx14
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/po/page.tsx17
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/pq_new/page.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/rfq-last/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/risk-management/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/tbe-last/page.tsx15
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/vendor-candidates/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/vendor-investigation/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/vendor-pool/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/vendor-regular-registrations/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(procurement)/vendors/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-hull/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-ship/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-top/page.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/tech-contact-possible-items/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/tech-project-avl/page.tsx4
-rw-r--r--app/[lng]/evcp/(evcp)/(sales)/tech-vendors/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/approval/line/page.tsx7
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/approval/log/page.tsx14
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/approval/template/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/change-vendor/page.tsx20
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/email-log/page.tsx6
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/email-template/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/email-whitelist/page.tsx9
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/information/page.tsx4
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/integration-log/page.tsx13
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/integration/page.tsx13
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/login-history/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/menu-access-dept/page.tsx22
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/menu-access/page.tsx10
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/menu-list/page.tsx97
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/notice/page.tsx14
-rw-r--r--app/[lng]/evcp/(evcp)/(system)/page-visits/page.tsx8
-rw-r--r--app/[lng]/evcp/(evcp)/edp-progress/page.tsx10
-rw-r--r--app/[lng]/evcp/(evcp)/layout.tsx18
-rw-r--r--app/[lng]/partners/(partners)/basic-contract/page.tsx10
-rw-r--r--app/[lng]/partners/(partners)/bid/page.tsx13
-rw-r--r--app/[lng]/partners/(partners)/document-list-ship/page.tsx6
-rw-r--r--app/[lng]/partners/(partners)/evaluation/page.tsx10
-rw-r--r--app/[lng]/partners/(partners)/general-contract-review/page.tsx14
-rw-r--r--app/[lng]/partners/(partners)/layout.tsx4
-rw-r--r--app/[lng]/partners/(partners)/pcr/page.tsx14
-rw-r--r--app/[lng]/partners/(partners)/po/page.tsx8
-rw-r--r--app/[lng]/partners/(partners)/pq_new/page.tsx22
-rw-r--r--app/[lng]/partners/(partners)/rfq-last/page.tsx12
-rw-r--r--app/[lng]/partners/(partners)/swp-document-upload/page.tsx13
-rw-r--r--app/[lng]/partners/(partners)/tbe-last/page.tsx8
-rw-r--r--app/[lng]/partners/(partners)/techsales/rfq-offshore-hull/page.tsx10
-rw-r--r--app/[lng]/partners/(partners)/techsales/rfq-offshore-top/page.tsx10
-rw-r--r--app/[lng]/partners/(partners)/techsales/rfq-ship/page.tsx11
73 files changed, 503 insertions, 277 deletions
diff --git a/app/[lng]/evcp/(evcp)/(eng)/cover/page.tsx b/app/[lng]/evcp/(evcp)/(eng)/cover/page.tsx
index 9f2b2e61..891296db 100644
--- a/app/[lng]/evcp/(evcp)/(eng)/cover/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(eng)/cover/page.tsx
@@ -9,12 +9,16 @@ import { searchParamsProjectsCache } from "@/lib/projects/validation"
import { InformationButton } from "@/components/information/information-button"
import { getProjectListsForCover } from "@/lib/cover/service"
import { ProjectsTableForCover } from "@/lib/cover/table/projects-table"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = searchParamsProjectsCache.parse(searchParams)
@@ -35,7 +39,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 프로젝트 리스트
+ {t('menu.engineering_management.cover')}
</h2>
<InformationButton pagePath="evcp/projects" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(eng)/document-list-ship/page.tsx b/app/[lng]/evcp/(evcp)/(eng)/document-list-ship/page.tsx
index 822e7cd4..018c5e73 100644
--- a/app/[lng]/evcp/(evcp)/(eng)/document-list-ship/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(eng)/document-list-ship/page.tsx
@@ -15,11 +15,15 @@ import { getUserVendorDocumentStats, getUserVendorDocumentStatsAll, getUserVendo
import { UserVendorDocumentDisplay } from "@/components/ship-vendor-document/user-vendor-document-table-container"
import { InformationButton } from "@/components/information/information-button"
import { UserVendorALLDocumentDisplay } from "@/components/ship-vendor-document-all/user-vendor-document-table-container"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = searchParamsShipDocuCache.parse(searchParams)
const validFilters = getValidFilters(search.filters)
@@ -35,11 +39,11 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 문서 관리
+ {t('menu.engineering_management.document_list_ship')}
</h2>
</div>
{/* <p className="text-muted-foreground">
- 소속 회사의 모든 도서/도면을 확인하고 관리합니다.
+ {t('menu.engineering_management.document_list_ship_desc')}
</p> */}
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(eng)/vendor-data/layout.tsx b/app/[lng]/evcp/(evcp)/(eng)/vendor-data/layout.tsx
index 7d00359c..be6bb5eb 100644
--- a/app/[lng]/evcp/(evcp)/(eng)/vendor-data/layout.tsx
+++ b/app/[lng]/evcp/(evcp)/(eng)/vendor-data/layout.tsx
@@ -5,12 +5,19 @@ import { Shell } from "@/components/shell"
import { getVendorProjectsAndContracts } from "@/lib/vendor-data/services"
import { VendorDataContainer } from "@/components/vendor-data/vendor-data-container"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
+
// Layout 컴포넌트는 서버 컴포넌트입니다
export default async function VendorDataLayout({
+ params,
children,
}: {
+ params: Promise<{ lng: string }>
children: React.ReactNode
}) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
+
// evcp: 전체 계약 대상으로 프로젝트 데이터 가져오기
const projects = await getVendorProjectsAndContracts()
@@ -32,7 +39,7 @@ export default async function VendorDataLayout({
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 데이터 입력
+ {t('menu.engineering_management.vendor_data')}
</h2>
<InformationButton pagePath="partners/vendor-data" />
</div>
@@ -64,4 +71,4 @@ export default async function VendorDataLayout({
</section>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/buyer-signature/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/buyer-signature/page.tsx
index 96bf783c..dfbd605b 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/buyer-signature/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/buyer-signature/page.tsx
@@ -15,7 +15,7 @@ export default async function BuyerSignaturePage(props: { params: Promise<{ lng:
<div>
<h1 className="text-3xl font-bold">{t('menu.master_data.buyer_signature')}</h1>
<p className="text-muted-foreground mt-2">
- 계약서에 자동으로 적용될 삼성중공업 서명을 관리합니다.
+ {t('menu.master_data.buyer_signaturee_desc')}
</p>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/esg-check-list/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/esg-check-list/page.tsx
index a573c77b..4575e65b 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/esg-check-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/esg-check-list/page.tsx
@@ -9,14 +9,18 @@ import { getEsgEvaluations } from "@/lib/esg-check-list/service"
import { getEsgEvaluationsSchema } from "@/lib/esg-check-list/validation"
import { EsgEvaluationsTable } from "@/lib/esg-check-list/table/esg-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = getEsgEvaluationsSchema.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -35,7 +39,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- ESG 자가진단평가서 항목 관리
+ {t('menu.master_data.esg_checklist')}
</h2>
<InformationButton pagePath="evcp/esg-check-list" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/evaluation-check-list/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/evaluation-check-list/page.tsx
index ccd6766b..5547b097 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/evaluation-check-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/evaluation-check-list/page.tsx
@@ -9,10 +9,12 @@ import { Skeleton } from '@/components/ui/skeleton';
import { Suspense } from 'react';
import { type SearchParams } from '@/types/table';
import { InformationButton } from '@/components/information/information-button';
+import { useTranslation } from '@/i18n';
// ----------------------------------------------------------------------------------------------------
/* TYPES */
interface EvaluationCriteriaPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
@@ -23,6 +25,8 @@ async function EvaluationCriteriaPage(props: EvaluationCriteriaPageProps) {
const searchParams = await props.searchParams;
const search = searchParamsCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const promises = Promise.all([
getRegEvalCriteria({
...search,
@@ -37,7 +41,7 @@ async function EvaluationCriteriaPage(props: EvaluationCriteriaPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 평가기준표 관리
+ {t('menu.master_data.evaluation_checklist')}
</h2>
<InformationButton pagePath="evcp/evaluation-check-list" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/evaluation-target-list/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/evaluation-target-list/page.tsx
index 325037d8..b42c2037 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/evaluation-target-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/evaluation-target-list/page.tsx
@@ -9,6 +9,7 @@ import { getDefaultEvaluationYear, searchParamsEvaluationTargetsCache } from "@/
import { getEvaluationTargets } from "@/lib/evaluation-target-list/service"
import { InformationButton } from "@/components/information/information-button"
import { EvaluationTargetsTable } from "@/lib/evaluation-target-list/table/evaluation-target-table"
+import { useTranslation } from "@/i18n"
export const dynamic = 'force-dynamic'
export const revalidate = 0
@@ -19,11 +20,14 @@ export const metadata: Metadata = {
}
interface EvaluationTargetsPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function EvaluationTargetsPage(props: EvaluationTargetsPageProps) {
const searchParams = await props.searchParams
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
// ✅ 간소화된 파싱
const search = searchParamsEvaluationTargetsCache.parse(searchParams)
@@ -42,7 +46,7 @@ export default async function EvaluationTargetsPage(props: EvaluationTargetsPage
<div className="flex items-center justify-between space-y-2">
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 평가 대상 관리
+ {t('menu.master_data.evaluation_target')}
</h2>
<InformationButton pagePath="evcp/evaluation-target-list" />
<Badge variant="outline" className="text-sm">
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/general-contract-template/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/general-contract-template/page.tsx
index 8a652690..c82f6b5a 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/general-contract-template/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/general-contract-template/page.tsx
@@ -9,14 +9,18 @@ import { getContractTemplates } from "@/lib/general-contract-template/service"
import { searchParamsTemplatesCache } from "@/lib/general-contract-template/validations"
import { ContractTemplateTable } from "@/lib/general-contract-template/template/general-contract-template"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsTemplatesCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -34,12 +38,12 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 일반계약(Contract) 표준양식 관리
+ {t('menu.master_data.general_contract_template')}
</h2>
<InformationButton pagePath="evcp/general-contract-template" />
</div>
<p className="text-muted-foreground mt-2">
- 다양한 계약 유형의 표준양식을 관리합니다. LO, FA, PO, CS, EU 등 계약 종류별 템플릿을 등록하고 편집할 수 있습니다.
+ {t('menu.master_data.general_contract_template_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/material-groups/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/material-groups/page.tsx
index 3d019182..708fac1e 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/material-groups/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/material-groups/page.tsx
@@ -15,14 +15,17 @@ import { MaterialGroupTable } from "@/lib/material-groups/table/material-group-t
import { InformationButton } from "@/components/information/information-button"
import { MaterialGroupSyncButton } from "@/components/material-groups/sync-button"
import { searchParamsCache } from "@/lib/material-groups/validations"
+import { useTranslation } from "@/i18n"
interface MaterialGroupPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function MaterialGroupPage(props: MaterialGroupPageProps) {
const searchParams = await props.searchParams
-
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
// searchParamsCache를 사용해서 파라미터 파싱
const search = searchParamsCache.parse(searchParams)
@@ -43,12 +46,12 @@ export default async function MaterialGroupPage(props: MaterialGroupPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 자재그룹
+ {t('menu.master_data.material_master')}
</h2>
<InformationButton pagePath="evcp/material-groups" />
</div>
<p className="text-muted-foreground">
- MDG로부터 수신된 자재그룹 정보
+ {t('menu.master_data.material_master_desc')}
</p>
</div>
<div className="flex items-center gap-2">
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/p-items/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/p-items/page.tsx
index 2b907a75..fa0cef19 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/p-items/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/p-items/page.tsx
@@ -8,14 +8,17 @@ import { getProcurementItems } from "@/lib/procurement-items/service"
import { ProcurementItemsTable } from "@/lib/procurement-items/table/procurement-items-table"
import { searchParamsCache } from "@/lib/procurement-items/validations"
import { InformationButton } from "@/components/information/information-button"
-
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -33,12 +36,12 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 1회성 품목 관리
+ {t('menu.master_data.procurement_items')}
</h2>
<InformationButton pagePath="evcp/procurement-items" />
</div>
<p className="text-muted-foreground">
- 입찰에서 사용하는 1회성 품목을 등록하고 관리합니다.
+ {t('menu.master_data.procurement_items_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/payment-conditions/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/payment-conditions/page.tsx
index 49724328..ff6d24b2 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/payment-conditions/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/payment-conditions/page.tsx
@@ -8,7 +8,9 @@ import { SearchParamsCache } from "@/lib/payment-terms/validations";
import { getPaymentTerms } from "@/lib/payment-terms/service";
import { PaymentTermsTable } from "@/lib/payment-terms/table/payment-terms-table";
import { InformationButton } from "@/components/information/information-button";
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>;
}
@@ -16,6 +18,8 @@ export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams;
const search = SearchParamsCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const promises = Promise.all([
getPaymentTerms({
@@ -29,7 +33,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">지급 조건 관리</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.master_data.payment_conditions')}</h2>
<InformationButton pagePath="evcp/payment-conditions" />
</div>
{/* <p className="text-muted-foreground">
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/pq-criteria/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/pq-criteria/page.tsx
index 1a337cc9..e83696ce 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/pq-criteria/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/pq-criteria/page.tsx
@@ -7,14 +7,18 @@ import { searchParamsCache } from "@/lib/pq/validations"
import { getPQLists } from "@/lib/pq/service"
import { PqListsTable } from "@/lib/pq/table/pq-lists-table"
import { getProjects } from "@/lib/pq/service"
+import { useTranslation } from "@/i18n"
interface ProjectPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function ProjectPage(props: ProjectPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
// filters가 없는 경우를 처리
const validFilters = getValidFilters(search.filters)
@@ -33,7 +37,7 @@ export default async function ProjectPage(props: ProjectPageProps) {
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- PQ 리스트 관리
+ {t('menu.master_data.pq_criteria')}
</h2>
{/* <p className="text-muted-foreground">
협력업체 등록을 위한, 협력업체가 제출할 PQ 항목을: 프로젝트별로 관리할 수 있습니다.
diff --git a/app/[lng]/evcp/(evcp)/(master-data)/vendor-check-list/page.tsx b/app/[lng]/evcp/(evcp)/(master-data)/vendor-check-list/page.tsx
index 955c95f0..4cc5a9a0 100644
--- a/app/[lng]/evcp/(evcp)/(master-data)/vendor-check-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(master-data)/vendor-check-list/page.tsx
@@ -9,14 +9,19 @@ import { getGenralEvaluationsSchema } from "@/lib/general-check-list/validation"
import { GeneralEvaluationsTable } from "@/lib/general-check-list/table/general-check-list-table"
import { getGeneralEvaluations } from "@/lib/general-check-list/service"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
+
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = getGenralEvaluationsSchema.parse(searchParams)
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -35,7 +40,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 평가자료 문항 관리
+ {t('menu.master_data.vendor_checklist')}
</h2>
<InformationButton pagePath="evcp/vendor-check-list" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/avl/avl-page-client.tsx b/app/[lng]/evcp/(evcp)/(procurement)/avl/avl-page-client.tsx
index 7152bdc2..cb191dd4 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/avl/avl-page-client.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/avl/avl-page-client.tsx
@@ -7,6 +7,8 @@ import { getAvlLists } from "@/lib/avl/service"
import { AvlListItem } from "@/lib/avl/types"
import { toast } from "sonner"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n/client"
+import { useParams } from "next/navigation"
interface AvlPageClientProps {
initialData: AvlListItem[]
@@ -17,6 +19,9 @@ export function AvlPageClient({ initialData }: AvlPageClientProps) {
const [isLoading, setIsLoading] = useState(false)
const [registrationMode, setRegistrationMode] = useState<'standard' | 'project' | null>(null)
+ const params = useParams<{lng: string}>()
+ const lng = params?.lng ?? 'ko'
+ const {t} = useTranslation(lng, 'menu')
// 초기 데이터 설정
useEffect(() => {
setAvlListData(initialData)
@@ -73,7 +78,7 @@ export function AvlPageClient({ initialData }: AvlPageClientProps) {
{/* info button and header section */}
<div className="flex items-center gap-2 mt-2">
<h2 className="text-2xl font-bold tracking-tight">
- AVL(Approved Vendor List) 목록
+ {t('menu.vendor_management.avl_management')}
</h2>
<InformationButton pagePath="evcp/avl" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/basic-contract/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/basic-contract/page.tsx
index 66b3ee31..57fceadf 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/basic-contract/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/basic-contract/page.tsx
@@ -9,15 +9,18 @@ import { getBasicContracts } from "@/lib/basic-contract/service"
import { searchParamsCache } from "@/lib/basic-contract/validations"
import { BasicContractsTable } from "@/lib/basic-contract/status/basic-contract-table"
import { InformationButton } from "@/components/information/information-button"
-
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -36,7 +39,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 기본계약서/서약서 관리
+ {t('menu.vendor_management.basic_contract')}
</h2>
<InformationButton pagePath="evcp/basic-contract" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/bid-failure/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/bid-failure/page.tsx
index b6c181dc..254fdc13 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/bid-failure/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/bid-failure/page.tsx
@@ -2,6 +2,7 @@ import { Metadata } from 'next'
import { getBiddingsForFailure } from '@/lib/bidding/service'
import { GetBiddingsSchema, searchParamsCache } from '@/lib/bidding/validation'
import { BiddingsFailureTable } from '@/lib/bidding/failure/biddings-failure-table'
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: '폐찰 및 재입찰',
@@ -9,15 +10,19 @@ export const metadata: Metadata = {
}
interface BiddingFailurePageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<Record<string, string | string[] | undefined>>
}
export default async function BiddingFailurePage({
+ params,
searchParams,
}: BiddingFailurePageProps) {
// URL 파라미터 검증
const searchParamsResolved = await searchParams
const search = searchParamsCache.parse(searchParamsResolved)
+ const {lng} = await params
+ const {t} = await useTranslation(lng, 'menu')
// 데이터 조회
const biddingsPromise = getBiddingsForFailure(search)
@@ -26,9 +31,9 @@ export default async function BiddingFailurePage({
<div className="flex flex-col gap-4 p-4">
<div className="flex items-center justify-between">
<div>
- <h1 className="text-2xl font-bold tracking-tight">폐찰 및 재입찰</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.procurement.bid_failure')}</h1>
<p className="text-muted-foreground">
- 유찰된 입찰 내역을 확인하고 재입찰을 진행할 수 있습니다.
+ {t('menu.procurement.bid_failure_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/bid-receive/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/bid-receive/page.tsx
index 4f6e9715..a087b09f 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/bid-receive/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/bid-receive/page.tsx
@@ -2,6 +2,7 @@ import { Metadata } from 'next'
import { getBiddingsForReceive } from '@/lib/bidding/service'
import { GetBiddingsSchema, searchParamsCache } from '@/lib/bidding/validation'
import { BiddingsReceiveTable } from '@/lib/bidding/receive/biddings-receive-table'
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: '입찰서 접수 및 마감',
@@ -9,15 +10,19 @@ export const metadata: Metadata = {
}
interface BiddingReceivePageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<Record<string, string | string[] | undefined>>
}
export default async function BiddingReceivePage({
+ params,
searchParams,
}: BiddingReceivePageProps) {
// URL 파라미터 검증
const searchParamsResolved = await searchParams
const search = searchParamsCache.parse(searchParamsResolved)
+ const {lng} = await params
+ const {t} = await useTranslation(lng, 'menu')
// 데이터 조회
const biddingsPromise = getBiddingsForReceive(search)
@@ -26,9 +31,9 @@ export default async function BiddingReceivePage({
<div className="flex flex-col gap-4 p-4">
<div className="flex items-center justify-between">
<div>
- <h1 className="text-2xl font-bold tracking-tight">입찰서 접수 및 마감</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.procurement.bid_receive')}</h1>
<p className="text-muted-foreground">
- 입찰서 접수 현황을 확인하고 개찰을 진행할 수 있습니다.
+ {t('menu.procurement.bid_receive_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/bid-selection/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/bid-selection/page.tsx
index 40b714de..f2fa33cd 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/bid-selection/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/bid-selection/page.tsx
@@ -1,23 +1,22 @@
-import { Metadata } from 'next'
import { getBiddingsForSelection } from '@/lib/bidding/service'
import { GetBiddingsSchema, searchParamsCache } from '@/lib/bidding/validation'
import { BiddingsSelectionTable } from '@/lib/bidding/selection/biddings-selection-table'
-
-export const metadata: Metadata = {
- title: '입찰선정',
- description: '개찰 이후 입찰가를 확인하고 낙찰업체를 선정할 수 있습니다.',
-}
+import { useTranslation } from "@/i18n"
interface BiddingSelectionPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<Record<string, string | string[] | undefined>>
}
export default async function BiddingSelectionPage({
+ params,
searchParams,
}: BiddingSelectionPageProps) {
// URL 파라미터 검증
const searchParamsResolved = await searchParams
const search = searchParamsCache.parse(searchParamsResolved)
+ const {lng} = await params
+ const {t} = await useTranslation(lng, 'menu')
// 데이터 조회
const biddingsPromise = getBiddingsForSelection(search)
@@ -26,9 +25,9 @@ export default async function BiddingSelectionPage({
<div className="flex flex-col gap-4 p-4">
<div className="flex items-center justify-between">
<div>
- <h1 className="text-2xl font-bold tracking-tight">입찰선정</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.procurement.bid_selection')}</h1>
<p className="text-muted-foreground">
- 개찰 이후 입찰가를 확인하고 낙찰업체를 선정할 수 있습니다.
+ {t('menu.procurement.bid_selection_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/bid/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/bid/page.tsx
index 973593d8..55dbae32 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/bid/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/bid/page.tsx
@@ -17,6 +17,7 @@ export const metadata = {
}
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
@@ -24,6 +25,7 @@ export default async function BiddingsPage(props: IndexPageProps) {
// ✅ nuqs searchParamsCache로 파싱 (타입 안전성 보장)
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
const validFilters = getValidFilters(search.filters)
@@ -42,7 +44,7 @@ export default async function BiddingsPage(props: IndexPageProps) {
{/* ═══════════════════════════════════════════════════════════════ */}
{/* 페이지 헤더 */}
{/* ═══════════════════════════════════════════════════════════════ */}
- <BiddingsPageHeader />
+ <BiddingsPageHeader lng={lng} />
{/* ═══════════════════════════════════════════════════════════════ */}
{/* 메인 테이블 */}
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/evaluation-input/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/evaluation-input/page.tsx
index 51478cc0..635169ce 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/evaluation-input/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/evaluation-input/page.tsx
@@ -12,8 +12,10 @@ import { LogIn } from "lucide-react"
import { getSHIEvaluationSubmissions } from "@/lib/evaluation-submit/service"
import { getSHIEvaluationsSubmitSchema } from "@/lib/evaluation-submit/validation"
import { SHIEvaluationSubmissionsTable } from "@/lib/evaluation-submit/table/submit-table"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
@@ -21,7 +23,9 @@ export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = getSHIEvaluationsSubmitSchema.parse(searchParams)
const validFilters = getValidFilters(search.filters)
-
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
+
// Get session
const session = await getServerSession(authOptions)
@@ -34,7 +38,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 정기평가 입력
+ {t('menu.vendor_management.evaluation_input')}
</h2>
</div>
{/* <p className="text-muted-foreground">
@@ -74,7 +78,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 정기평가 입력
+ {t('menu.vendor_management.evaluation_input')}
</h2>
</div>
</div>
@@ -104,7 +108,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 정기평가 입력
+ {t('menu.vendor_management.evaluation_input')}
</h2>
{/* <p className="text-muted-foreground">
요청된 정기평가를 입력하고 제출할 수 있습니다.
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/evaluation/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/evaluation/page.tsx
index 0d3848d9..bf30cfc9 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/evaluation/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/evaluation/page.tsx
@@ -24,6 +24,7 @@ import {
type GetEvaluationsSchema
} from "@/lib/evaluation/validation"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "협력업체 정기평가",
@@ -31,6 +32,7 @@ export const metadata: Metadata = {
}
interface PeriodicEvaluationsPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
@@ -133,6 +135,8 @@ function AggregatedModeNotice({ isAggregated }: { isAggregated: boolean }) {
export default async function PeriodicEvaluationsPage(props: PeriodicEvaluationsPageProps) {
const searchParams = await props.searchParams
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
// ✅ nuqs 기반 파라미터 파싱
const search = searchParamsEvaluationsCache.parse(searchParams)
@@ -156,7 +160,7 @@ export default async function PeriodicEvaluationsPage(props: PeriodicEvaluations
<div className="flex items-center gap-2">
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 정기평가
+ {t('menu.vendor_management.evaluation')}
</h2>
<InformationButton pagePath="evcp/evaluation" />
{/* <ProcessGuidePopover /> */}
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/general-contracts/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/general-contracts/page.tsx
index a6d5057c..96f03d09 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/general-contracts/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/general-contracts/page.tsx
@@ -12,6 +12,7 @@ import { GeneralContractsTable } from "@/lib/general-contracts/main/general-cont
import { getValidFilters } from "@/lib/data-table"
import { type SearchParams } from "@/types/table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
export const metadata = {
title: "일반계약 관리",
@@ -19,10 +20,13 @@ export const metadata = {
}
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function GeneralContractsPage(props: IndexPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
// ✅ searchParams 파싱
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
@@ -52,12 +56,12 @@ export default async function GeneralContractsPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 일반계약 관리
+ {t('menu.procurement.general_contract')}
</h2>
<InformationButton pagePath="evcp/general-contracts" />
</div>
<p className="text-muted-foreground">
- 일반계약을 생성하고 관리할 수 있습니다. 계약 상세정보, 품목정보, 납품확인서 등을 관리할 수 있습니다.
+ {t('menu.procurement.general_contract_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/itb-create/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/itb-create/page.tsx
index 54040e7f..77dc54ee 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/itb-create/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/itb-create/page.tsx
@@ -12,17 +12,16 @@ import Link from "next/link";
import { searchParamsPurchaseRequestCache } from "@/lib/itb/validations";
import { getAllPurchaseRequests, getPurchaseRequestStats } from "@/lib/itb/service";
import { PurchaseRequestsTable } from "@/lib/itb/table/purchase-requests-table";
+import { useTranslation } from "@/i18n"
interface PurchaseRequestsPageProps {
- params: {
- lng: string;
- };
+ params: Promise<{ lng: string }>;
searchParams: Promise<SearchParams>;
}
export default async function PurchaseRequestsPage(props: PurchaseRequestsPageProps) {
- const resolvedParams = await props.params;
- const lng = resolvedParams.lng;
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
@@ -44,10 +43,10 @@ export default async function PurchaseRequestsPage(props: PurchaseRequestsPagePr
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 구매 요청 관리
+ {t('menu.engineering_management.itb')}
</h2>
<p className="text-muted-foreground">
- 프로젝트별 자재 구매 요청을 생성하고 관리합니다.
+ {t('menu.engineering_management.itb_desc')}
</p>
</div>
</div>
@@ -161,4 +160,4 @@ async function PurchaseRequestStats({
export const metadata = {
title: "Purchase Request Management",
description: "Create and manage material purchase requests for projects",
-}; \ No newline at end of file
+};
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/pcr/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/pcr/page.tsx
index 7617bf58..22e0c124 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/pcr/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/pcr/page.tsx
@@ -5,12 +5,17 @@ import { InformationButton } from "@/components/information/information-button"
import { PcrTable } from "@/lib/pcr/table/pcr-table";
import { getPcrPoList } from "@/lib/pcr/service";
+import { useTranslation } from "@/i18n"
export const metadata = {
title: "PCR 관리",
description: "Purchase Change Request를 생성하고 관리할 수 있습니다.",
};
+interface IndexPageProps {
+ params: Promise<{ lng: string }>
+}
+
async function PcrTableWrapper() {
// 기본 데이터 조회 (EvcP용 - 모든 데이터 조회)
const tableData = await getPcrPoList({
@@ -21,7 +26,10 @@ async function PcrTableWrapper() {
return <PcrTable tableData={tableData} isEvcpPage={true} currentVendorId={undefined} />;
}
-export default function PcrPage() {
+export default async function PcrPage({ params }: IndexPageProps) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
+
return (
<Shell className="gap-4">
{/* ═══════════════════════════════════════════════════════════════ */}
@@ -32,12 +40,12 @@ export default function PcrPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- PCR 관리
+ {t('menu.procurement.pcr')}
</h2>
<InformationButton pagePath="evcp/pcr" />
</div>
<p className="text-muted-foreground">
- Purchase Change Request를 생성하고 관리할 수 있습니다. PCR 승인 상태, 변경 구분, PO/계약 정보 등을 확인할 수 있습니다.
+ {t('menu.procurement.pcr_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/po/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/po/page.tsx
index 292ef1cb..59b793ab 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/po/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/po/page.tsx
@@ -1,4 +1,4 @@
-import * as React from "react"
+
import { type SearchParams } from "@/types/table"
import { getValidFilters } from "@/lib/data-table"
@@ -9,14 +9,19 @@ import { getVendorPOs } from "@/lib/po/vendor-table/service"
import { vendorPoSearchParamsCache } from "@/lib/po/vendor-table/validations"
import { ShiVendorPoTable } from "@/lib/po/vendor-table/shi-vendor-po-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
+import { Suspense } from "react"
interface VendorPOPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function VendorPONew(props: VendorPOPageProps) {
const searchParams = await props.searchParams
const search = vendorPoSearchParamsCache.parse(searchParams)
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -34,7 +39,7 @@ export default async function VendorPONew(props: VendorPOPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- PO/계약 관리
+ {t('menu.procurement.po_issuance')}
</h2>
<InformationButton pagePath="evcp/po-new" />
</div>
@@ -42,9 +47,9 @@ export default async function VendorPONew(props: VendorPOPageProps) {
</div>
</div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- </React.Suspense>
- <React.Suspense
+ <Suspense fallback={<Skeleton className="h-7 w-52" />}>
+ </Suspense>
+ <Suspense
fallback={
<DataTableSkeleton
columnCount={8}
@@ -56,7 +61,7 @@ export default async function VendorPONew(props: VendorPOPageProps) {
}
>
<ShiVendorPoTable promises={promises} />
- </React.Suspense>
+ </Suspense>
</Shell>
)
}
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/pq_new/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/pq_new/page.tsx
index 6a992ee5..e1fcd80d 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/pq_new/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/pq_new/page.tsx
@@ -8,12 +8,15 @@ import { searchParamsPQReviewCache } from "@/lib/pq/validations"
import { getPQSubmissions } from "@/lib/pq/service"
import { PQSubmissionsTable } from "@/lib/pq/pq-review-table-new/vendors-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
+
export const metadata: Metadata = {
title: "협력업체 PQ/실사 현황",
description: "",
}
interface PQReviewPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
@@ -21,6 +24,8 @@ export default async function PQReviewPage(props: PQReviewPageProps) {
const searchParams = await props.searchParams
const search = searchParamsPQReviewCache.parse(searchParams)
const validFilters = getValidFilters(search.filters)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
// 디버깅 로그 추가
console.log("=== PQ Page Debug ===");
@@ -71,7 +76,7 @@ export default async function PQReviewPage(props: PQReviewPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 PQ/실사 현황
+ {t('menu.vendor_management.pq_status')}
</h2>
<InformationButton pagePath="evcp/pq_new" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/rfq-last/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/rfq-last/page.tsx
index 6830dbe9..223046b7 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/rfq-last/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/rfq-last/page.tsx
@@ -23,6 +23,7 @@ import { RfqTable } from "@/lib/rfq-last/table/rfq-table";
import { getRfqs } from "@/lib/rfq-last/service";
import { searchParamsRfqCache } from "@/lib/rfq-last/validations";
import { InformationButton } from "@/components/information/information-button";
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "RFQ 관리",
@@ -30,6 +31,7 @@ export const metadata: Metadata = {
};
interface RfqPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>;
}
@@ -63,6 +65,8 @@ async function getTabCounts() {
export default async function RfqPage(props: RfqPageProps) {
const searchParams = await props.searchParams;
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
// nuqs 기반 파라미터 파싱
const search = searchParamsRfqCache.parse(searchParams);
@@ -89,7 +93,7 @@ export default async function RfqPage(props: RfqPageProps) {
<div className="flex items-center justify-between space-y-2">
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 견적목록관리
+ {t('menu.procurement.budget_rfq')}
</h2>
<InformationButton pagePath="evcp/rfq-last" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/risk-management/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/risk-management/page.tsx
index c372865e..d2334ba5 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/risk-management/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/risk-management/page.tsx
@@ -13,11 +13,13 @@ import { Skeleton } from '@/components/ui/skeleton';
import { Suspense } from 'react';
import { type DateRange } from 'react-day-picker';
import { type SearchParams } from '@/types/table';
+import { useTranslation } from "@/i18n"
// ----------------------------------------------------------------------------------------------------
/* TYPES */
interface RiskManagementPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>;
}
@@ -29,6 +31,8 @@ async function RiskManagementPage(props: RiskManagementPageProps) {
const searchParamsResult = await searchParams;
const search = searchParamsCache.parse(searchParamsResult);
const validFilters = getValidFilters(search.filters);
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const promises = Promise.all([
getRisksView({
...search,
@@ -52,12 +56,12 @@ async function RiskManagementPage(props: RiskManagementPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 리스크 관리
+ {t('menu.vendor_management.risk_by_agency')}
</h2>
<InformationButton pagePath="evcp/risk-management" />
</div>
<p className="text-muted-foreground">
- 신용평가사 정보를 기반으로 국내 협력업체 리스크를 관리할 수 있습니다.
+ {t('menu.vendor_management.risk_by_agency_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/tbe-last/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/tbe-last/page.tsx
index 61e7ce05..81d2af51 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/tbe-last/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/tbe-last/page.tsx
@@ -10,17 +10,16 @@ import { Shell } from "@/components/shell"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { Button } from "@/components/ui/button"
import { Plus } from "lucide-react"
+import { useTranslation } from "@/i18n"
interface TbeLastPageProps {
- params: {
- lng: string
- }
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function TbeLastPage(props: TbeLastPageProps) {
- const resolvedParams = await props.params
- const lng = resolvedParams.lng
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
@@ -41,10 +40,10 @@ export default async function TbeLastPage(props: TbeLastPageProps) {
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- Technical Bid Evaluation (TBE)
+ {t('menu.engineering_management.tbe')}
</h2>
<p className="text-muted-foreground">
- RFQ 발송 후 기술 평가를 진행하고 문서를 검토합니다.
+ {t('menu.engineering_management.tbe_desc')}
</p>
</div>
@@ -71,4 +70,4 @@ export default async function TbeLastPage(props: TbeLastPageProps) {
export const metadata = {
title: "TBE Management",
description: "Technical Bid Evaluation for RFQ responses",
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/vendor-candidates/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/vendor-candidates/page.tsx
index be6debce..04df8e6b 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/vendor-candidates/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/vendor-candidates/page.tsx
@@ -11,13 +11,17 @@ import { searchParamsCandidateCache } from "@/lib/vendor-candidates/validations"
import { VendorCandidateTable } from "@/lib/vendor-candidates/table/candidates-table"
import { DateRangePicker } from "@/components/date-range-picker"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCandidateCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -37,7 +41,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 발굴업체 등록 관리
+ {t('menu.vendor_management.candidates')}
</h2>
<InformationButton pagePath="evcp/vendor-candidates" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/vendor-investigation/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/vendor-investigation/page.tsx
index 1d7786a5..799c3b5a 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/vendor-investigation/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/vendor-investigation/page.tsx
@@ -10,13 +10,17 @@ import { VendorsInvestigationTable } from "@/lib/vendor-investigation/table/inve
import { getVendorsInvestigation } from "@/lib/vendor-investigation/service"
import { searchParamsInvestigationCache } from "@/lib/vendor-investigation/validations"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
searchParams: Promise<SearchParams>
+ params: Promise<{ lng: string }>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsInvestigationCache.parse(searchParams)
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -35,7 +39,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 실사 관리
+ {t('menu.vendor_management.investigation')}
</h2>
<InformationButton pagePath="evcp/vendor-investigation" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/vendor-pool/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/vendor-pool/page.tsx
index f18716a3..362974df 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/vendor-pool/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/vendor-pool/page.tsx
@@ -7,10 +7,16 @@ import { VendorPoolVirtualTable } from "@/lib/vendor-pool/table/vendor-pool-virt
import { Skeleton } from "@/components/ui/skeleton"
import type { VendorPoolItem } from "@/lib/vendor-pool/table/vendor-pool-table-columns"
import { toast } from "sonner"
+import { useTranslation } from "@/i18n/client"
+import { useParams } from "next/navigation"
+
export default function VendorPoolPage() {
const [data, setData] = React.useState<VendorPoolItem[]>([])
const [isLoading, setIsLoading] = React.useState(true)
+ const params = useParams<{lng: string}>()
+ const lng = params?.lng ?? 'ko'
+ const {t} = useTranslation(lng, 'menu')
// 전체 데이터 로드
const loadData = React.useCallback(async () => {
@@ -52,7 +58,7 @@ export default function VendorPoolPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- Vendor Pool
+ {t('menu.vendor_management.vendor_pool')}
</h2>
<InformationButton pagePath="evcp/vendor-pool" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/vendor-regular-registrations/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/vendor-regular-registrations/page.tsx
index e8433c55..4915edcd 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/vendor-regular-registrations/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/vendor-regular-registrations/page.tsx
@@ -10,13 +10,15 @@ import { Shell } from "@/components/shell"
import { fetchVendorRegularRegistrations } from "@/lib/vendor-regular-registrations/service"
import { VendorRegularRegistrationsTable } from "@/lib/vendor-regular-registrations/table/vendor-regular-registrations-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
-
-export default async function VendorRegularRegistrationsPage() {
+export default async function VendorRegularRegistrationsPage(props: {params: Promise<{lng: string}>}) {
const promises = Promise.all([
fetchVendorRegularRegistrations(),
])
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
return (
<Shell className="gap-2">
@@ -25,7 +27,7 @@ export default async function VendorRegularRegistrationsPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 정규업체 등록관리
+ {t('menu.vendor_management.vendor_regular_registrations')}
</h2>
<InformationButton pagePath="evcp/vendor-regular-registrations" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/vendors/page.tsx b/app/[lng]/evcp/(evcp)/(procurement)/vendors/page.tsx
index fb7bb14c..4a071ee0 100644
--- a/app/[lng]/evcp/(evcp)/(procurement)/vendors/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(procurement)/vendors/page.tsx
@@ -12,13 +12,17 @@ import { getVendors, getVendorStatusCounts } from "@/lib/vendors/service"
import { VendorsTable } from "@/lib/vendors/table/vendors-table"
import { Ellipsis } from "lucide-react"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -38,7 +42,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 협력업체 관리
+ {t('menu.vendor_management.vendors')}
</h2>
<InformationButton pagePath="evcp/vendors" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-hull/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-hull/page.tsx
index 97e53567..2ca48091 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-hull/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-hull/page.tsx
@@ -7,14 +7,18 @@ import { RFQListTable } from "@/lib/techsales-rfq/table/rfq-table"
import { type SearchParams } from "@/types/table"
import * as React from "react"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface HullRfqPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function HullRfqPage(props: HullRfqPageProps) {
// searchParams를 await하여 resolve
const searchParams = await props.searchParams
-
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
+
// 해양 HULL용 파라미터 파싱
const search = searchParamsHullCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -35,7 +39,7 @@ export default async function HullRfqPage(props: HullRfqPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 기술영업-해양 Hull Budgetary RFQ
+ {t('menu.tech_sales.budgetary_hull')}
</h2>
<InformationButton pagePath="evcp/budgetary-tech-sales-hull" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-ship/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-ship/page.tsx
index 779b9ac9..0791a9bd 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-ship/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-ship/page.tsx
@@ -7,14 +7,18 @@ import { RFQListTable } from "@/lib/techsales-rfq/table/rfq-table"
import { type SearchParams } from "@/types/table"
import * as React from "react"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface RfqPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function RfqPage(props: RfqPageProps) {
// searchParams를 await하여 resolve
const searchParams = await props.searchParams
-
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
+
// 조선용 파라미터 파싱
const search = searchParamsShipCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -35,7 +39,7 @@ export default async function RfqPage(props: RfqPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 기술영업-조선 Budgetary RFQ
+ {t('menu.tech_sales.budgetary_ship')}
</h2>
<InformationButton pagePath="evcp/budgetary-tech-sales-ship" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-top/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-top/page.tsx
index 5c96c85d..0949d9a0 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-top/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/budgetary-tech-sales-top/page.tsx
@@ -7,14 +7,17 @@ import { RFQListTable } from "@/lib/techsales-rfq/table/rfq-table"
import { type SearchParams } from "@/types/table"
import * as React from "react"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface HullRfqPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function HullRfqPage(props: HullRfqPageProps) {
// searchParams를 await하여 resolve
const searchParams = await props.searchParams
-
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
// 해양 TOP용 파라미터 파싱
const search = searchParamsTopCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -35,7 +38,7 @@ export default async function HullRfqPage(props: HullRfqPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 기술영업-해양 TOP Budgetary RFQ
+ {t('menu.tech_sales.budgetary_top')}
</h2>
<InformationButton pagePath="evcp/budgetary-tech-sales-top" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/tech-contact-possible-items/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/tech-contact-possible-items/page.tsx
index cf35530d..ad7c7b36 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/tech-contact-possible-items/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/tech-contact-possible-items/page.tsx
@@ -6,17 +6,22 @@ import { searchParamsCache } from "@/lib/contact-possible-items/validations"
import { ContactPossibleItemsTable } from "@/lib/contact-possible-items/table/contact-possible-items-table"
import { getValidFilters } from "@/lib/data-table"
import { type SearchParams } from "@/types/table"
+import { useTranslation } from "@/i18n"
interface ContactPossibleItemsPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function ContactPossibleItemsPage({
+ params,
searchParams,
}: ContactPossibleItemsPageProps) {
// ✅ searchParams 파싱
const resolvedSearchParams = await searchParams
const search = searchParamsCache.parse(resolvedSearchParams)
+ const {lng} = await params
+ const {t} = await useTranslation(lng, 'menu')
console.log("Parsed search params:", search)
@@ -39,10 +44,10 @@ export default async function ContactPossibleItemsPage({
<div className="flex items-center justify-between space-y-2">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 담당자별 자재 관리
+ {t('menu.tech_sales.contact_items')}
</h2>
<p className="text-muted-foreground">
- 기술영업 담당자별 자재를 관리합니다.
+ {t('menu.tech_sales.contact_items_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/tech-project-avl/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/tech-project-avl/page.tsx
index 4ce018cd..c9ec6075 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/tech-project-avl/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/tech-project-avl/page.tsx
@@ -12,6 +12,7 @@ import { getValidFilters } from "@/lib/data-table"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { Ellipsis } from "lucide-react"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
export interface PageProps {
params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
@@ -22,6 +23,7 @@ export default async function AcceptedQuotationsPage({
searchParams,
}: PageProps) {
const { lng } = await params
+ const {t} = await useTranslation(lng, 'menu')
const session = await getServerSession(authOptions)
if (!session) {
@@ -47,7 +49,7 @@ export default async function AcceptedQuotationsPage({
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 견적 Result 전송
+ {t('menu.tech_sales.result_transmission')}
</h2>
<InformationButton pagePath="evcp/tech-project-avl" />
</div>
diff --git a/app/[lng]/evcp/(evcp)/(sales)/tech-vendors/page.tsx b/app/[lng]/evcp/(evcp)/(sales)/tech-vendors/page.tsx
index 736a7bad..7475c274 100644
--- a/app/[lng]/evcp/(evcp)/(sales)/tech-vendors/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(sales)/tech-vendors/page.tsx
@@ -8,14 +8,18 @@ import { Shell } from "@/components/shell"
import { searchParamsCache } from "@/lib/tech-vendors/validations"
import { getTechVendors, getTechVendorStatusCounts } from "@/lib/tech-vendors/service"
import { TechVendorsTable } from "@/lib/tech-vendors/table/tech-vendors-table"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{lng: string}>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
+ const {lng} = await props.params
+ const {t} = await useTranslation(lng, 'menu')
const validFilters = getValidFilters(search.filters)
@@ -33,7 +37,7 @@ export default async function IndexPage(props: IndexPageProps) {
{/* 왼쪽: 타이틀 & 설명 */}
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">기술영업 협력업체 관리</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.tech_sales.vendors')}</h2>
{/* InformationButton은 필요시 추가 */}
{/* <InformationButton pagePath="evcp/tech-vendors" /> */}
</div>
diff --git a/app/[lng]/evcp/(evcp)/(system)/approval/line/page.tsx b/app/[lng]/evcp/(evcp)/(system)/approval/line/page.tsx
index 2e96b434..0e227e0b 100644
--- a/app/[lng]/evcp/(evcp)/(system)/approval/line/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/approval/line/page.tsx
@@ -9,16 +9,21 @@ import { getApprovalLineList } from '@/lib/approval-line/service';
import { SearchParamsApprovalLineCache } from '@/lib/approval-line/validations';
import { ApprovalLineTable } from '@/lib/approval-line/table/approval-line-table';
+import { useTranslation } from "@/i18n";
+
export const metadata: Metadata = {
title: '결재선 관리',
description: '결재용 결재선을 관리합니다.',
};
interface PageProps {
+ params: Promise<{ lng: string }>;
searchParams: Promise<SearchParams>;
}
export default async function ApprovalLinePage(props: PageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
const search = SearchParamsApprovalLineCache.parse(searchParams);
// getValidFilters 반환값이 undefined 인 경우 폴백
@@ -37,7 +42,7 @@ export default async function ApprovalLinePage(props: PageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">결재선 관리</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.information_system.approval_line')}</h2>
</div>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(system)/approval/log/page.tsx b/app/[lng]/evcp/(evcp)/(system)/approval/log/page.tsx
index f5b069df..d6ab6282 100644
--- a/app/[lng]/evcp/(evcp)/(system)/approval/log/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/approval/log/page.tsx
@@ -5,8 +5,16 @@ import { Skeleton } from "@/components/ui/skeleton";
import { ApprovalLogTable } from "@/lib/approval-log/table/approval-log-table";
import { getApprovalLogList } from "@/lib/approval-log/service";
import React from "react";
+import { useTranslation } from "@/i18n";
+
+interface approvalLogPageProps {
+ params: Promise<{ lng: string }>
+}
+
+export default async function ApprovalLogPage({ params }: approvalLogPageProps) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
-export default async function ApprovalLogPage() {
// 기본 데이터 조회 (첫 페이지, 기본 정렬)
const promises = Promise.all([
getApprovalLogList({
@@ -23,7 +31,7 @@ export default async function ApprovalLogPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 결재 로그
+ {t('menu.information_system.approval_log')}
</h2>
<InformationButton pagePath="evcp/approval/log" />
</div>
@@ -46,4 +54,4 @@ export default async function ApprovalLogPage() {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/approval/template/page.tsx b/app/[lng]/evcp/(evcp)/(system)/approval/template/page.tsx
index c5834b05..91118d90 100644
--- a/app/[lng]/evcp/(evcp)/(system)/approval/template/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/approval/template/page.tsx
@@ -8,6 +8,7 @@ import { getValidFilters } from '@/lib/data-table';
import { getApprovalTemplateList } from '@/lib/approval-template/service';
import { SearchParamsApprovalTemplateCache } from '@/lib/approval-template/validations';
import { ApprovalTemplateTable } from '@/lib/approval-template/table/approval-template-table';
+import { useTranslation } from "@/i18n";
export const metadata: Metadata = {
title: '결재 템플릿 관리',
@@ -15,10 +16,13 @@ export const metadata: Metadata = {
};
interface PageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>;
}
export default async function ApprovalTemplatePage(props: PageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
const search = SearchParamsApprovalTemplateCache.parse(searchParams);
// getValidFilters 반환값이 undefined 인 경우 폴백
@@ -37,7 +41,7 @@ export default async function ApprovalTemplatePage(props: PageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">결재 템플릿 관리</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.information_system.approval_template')}</h2>
</div>
</div>
</div>
@@ -66,4 +70,4 @@ export default async function ApprovalTemplatePage(props: PageProps) {
</React.Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/change-vendor/page.tsx b/app/[lng]/evcp/(evcp)/(system)/change-vendor/page.tsx
index 4b4b0a8d..8b4ba5b5 100644
--- a/app/[lng]/evcp/(evcp)/(system)/change-vendor/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/change-vendor/page.tsx
@@ -2,6 +2,11 @@ import * as React from 'react';
import { type Metadata } from 'next';
import { Shell } from '@/components/shell';
import { ChangeVendorClient } from './change-vendor-client';
+import { useTranslation } from "@/i18n";
+
+interface changeVendorPageProps {
+ params: Promise<{ lng: string }>
+}
export const metadata: Metadata = {
title: '벤더 변경',
@@ -10,15 +15,20 @@ export const metadata: Metadata = {
export const dynamic = 'force-dynamic';
-export default async function ChangeVendorPage() {
+export default async function ChangeVendorPage({ params }: changeVendorPageProps) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
+
return (
<Shell className="gap-6">
<div className="flex items-center justify-between space-y-2">
<div>
- <h2 className="text-2xl font-bold tracking-tight">벤더 변경</h2>
- <p className="text-muted-foreground">
- 유저를 검색하고 선택한 후, 해당 유저의 벤더를 변경할 수 있습니다.
- </p>
+ <h2 className="text-2xl font-bold tracking-tight">
+ {t('menu.information_system.change_vendor')}
+ </h2>
+ {/* <p className="text-muted-foreground"> */}
+ {/* 유저를 검색하고 선택한 후, 해당 유저의 벤더를 변경할 수 있습니다. */}
+ {/* </p> */}
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(system)/email-log/page.tsx b/app/[lng]/evcp/(evcp)/(system)/email-log/page.tsx
index 41001cc7..07699daf 100644
--- a/app/[lng]/evcp/(evcp)/(system)/email-log/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/email-log/page.tsx
@@ -7,6 +7,7 @@ import { SearchParams } from "@/types/table"
import { SearchParamsEmailLogCache } from "@/lib/email-log/validations"
import { getEmailLogList } from "@/lib/email-log/service"
import { EmailLogTable } from "@/lib/email-log/table/email-log-table"
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "이메일 발신 이력 조회",
@@ -14,10 +15,13 @@ export const metadata: Metadata = {
}
interface EmailLogPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function EmailLogPage(props: EmailLogPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = SearchParamsEmailLogCache.parse(searchParams)
@@ -31,7 +35,7 @@ export default async function EmailLogPage(props: EmailLogPageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">이메일 발신 이력 조회</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.information_system.email_log')}</h2>
</div>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/(system)/email-template/page.tsx b/app/[lng]/evcp/(evcp)/(system)/email-template/page.tsx
index 16c75dab..c4437994 100644
--- a/app/[lng]/evcp/(evcp)/(system)/email-template/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/email-template/page.tsx
@@ -15,6 +15,7 @@ import { Shell } from "@/components/shell"
import { getValidFilters } from "@/lib/data-table"
import { Skeleton } from "@/components/ui/skeleton"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "템플릿 관리",
@@ -22,10 +23,14 @@ export const metadata: Metadata = {
}
interface TemplatePageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function TemplatePage(props: TemplatePageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
+
const searchParams = await props.searchParams
const search = SearchParamsEmailTemplateCache.parse(searchParams)
@@ -48,7 +53,7 @@ export default async function TemplatePage(props: TemplatePageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 이메일 템플릿 관리
+ {t('menu.information_system.email_template')}
</h2>
{/* <InformationButton pagePath="evcp/equip-class" /> */}
</div>
@@ -73,4 +78,4 @@ export default async function TemplatePage(props: TemplatePageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/email-whitelist/page.tsx b/app/[lng]/evcp/(evcp)/(system)/email-whitelist/page.tsx
index 95abd556..2613ce65 100644
--- a/app/[lng]/evcp/(evcp)/(system)/email-whitelist/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/email-whitelist/page.tsx
@@ -17,6 +17,7 @@ import { WhitelistTable } from "@/lib/email-whitelist/table/whitelist-table"
import { Shell } from "@/components/shell"
import { Skeleton } from "@/components/ui/skeleton"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { useTranslation } from "@/i18n"
// export const metadata: Metadata = {
// title: "이메일 화이트리스트 관리",
@@ -24,11 +25,13 @@ import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
// }
interface WhitelistPageProps {
+ params: Promise<{ lng: string }>
searchParams: SearchParams
}
export default async function WhitelistPage(props: WhitelistPageProps) {
-
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
// 기본 검색 파라미터 처리
@@ -52,7 +55,7 @@ export default async function WhitelistPage(props: WhitelistPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 이메일 화이트리스트 관리
+ {t('menu.information_system.email_whitelist')}
</h2>
</div>
<p className="text-muted-foreground">
@@ -79,4 +82,4 @@ export default async function WhitelistPage(props: WhitelistPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/information/page.tsx b/app/[lng]/evcp/(evcp)/(system)/information/page.tsx
index 8a6d348b..ff8c7024 100644
--- a/app/[lng]/evcp/(evcp)/(system)/information/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/information/page.tsx
@@ -39,7 +39,7 @@ export default async function InformationPage({ params }: InformationPageProps)
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 안내사항 관리
+ {t('menu.information_system.information')}
</h2>
<InformationButton pagePath="/evcp/information" />
</div>
@@ -49,4 +49,4 @@ export default async function InformationPage({ params }: InformationPageProps)
<InformationClient initialData={translatedData} />
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/integration-log/page.tsx b/app/[lng]/evcp/(evcp)/(system)/integration-log/page.tsx
index c10a41ea..75796b98 100644
--- a/app/[lng]/evcp/(evcp)/(system)/integration-log/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/integration-log/page.tsx
@@ -7,12 +7,16 @@ import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
import { SearchParamsCache } from "@/lib/integration-log/validations";
import { getIntegrationLogs } from "@/lib/integration-log/service";
import { IntegrationLogTable } from "@/lib/integration-log/table/integration-log-table";
+import { useTranslation } from "@/i18n";
interface IntegrationLogPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>;
}
export default async function IntegrationLogPage(props: IntegrationLogPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
const search = SearchParamsCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -28,10 +32,9 @@ export default async function IntegrationLogPage(props: IntegrationLogPageProps)
<Shell className="gap-2">
<div className="flex items-center justify-between space-y-2">
<div>
- <h2 className="text-2xl font-bold tracking-tight">인터페이스 이력 조회</h2>
- <p className="text-muted-foreground">
- 인터페이스 실행 이력을 조회합니다. 검색, 필터링, 정렬이 가능합니다.
- </p>
+ <h2 className="text-2xl font-bold tracking-tight">
+ {t('menu.information_system.integration_log')}
+ </h2>
</div>
</div>
<React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
@@ -50,4 +53,4 @@ export default async function IntegrationLogPage(props: IntegrationLogPageProps)
</React.Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/integration/page.tsx b/app/[lng]/evcp/(evcp)/(system)/integration/page.tsx
index f2266bca..6aeaf041 100644
--- a/app/[lng]/evcp/(evcp)/(system)/integration/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/integration/page.tsx
@@ -7,12 +7,16 @@ import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
import { SearchParamsCache } from "@/lib/integration/validations";
import { getIntegrations } from "@/lib/integration/service";
import { IntegrationTable } from "@/lib/integration/table/integration-table";
+import { useTranslation } from "@/i18n";
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>;
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
const search = SearchParamsCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -28,10 +32,9 @@ export default async function IndexPage(props: IndexPageProps) {
<Shell className="gap-2">
<div className="flex items-center justify-between space-y-2">
<div>
- <h2 className="text-2xl font-bold tracking-tight">인터페이스 관리</h2>
- <p className="text-muted-foreground">
- 시스템 인터페이스를 등록, 수정, 삭제할 수 있습니다.
- </p>
+ <h2 className="text-2xl font-bold tracking-tight">
+ {t('menu.information_system.integration_list')}
+ </h2>
</div>
</div>
<React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
@@ -50,4 +53,4 @@ export default async function IndexPage(props: IndexPageProps) {
</React.Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/login-history/page.tsx b/app/[lng]/evcp/(evcp)/(system)/login-history/page.tsx
index dbc8089f..3c3d9255 100644
--- a/app/[lng]/evcp/(evcp)/(system)/login-history/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/login-history/page.tsx
@@ -9,12 +9,16 @@ import { Shell } from "@/components/shell"
import { getLoginSessions } from "@/lib/login-session/service"
import { searchParamsCache } from "@/lib/login-session/validation"
import { LoginSessionsTable } from "@/lib/login-session/table/login-sessions-table"
+import { useTranslation } from "@/i18n"
interface LoginHistoryPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function LoginHistoryPage(props: LoginHistoryPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
@@ -34,7 +38,7 @@ export default async function LoginHistoryPage(props: LoginHistoryPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 로그인 세션 이력
+ {t('menu.information_system.login_history')}
</h2>
</div>
{/* <p className="text-muted-foreground">
@@ -63,4 +67,4 @@ export default async function LoginHistoryPage(props: LoginHistoryPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/menu-access-dept/page.tsx b/app/[lng]/evcp/(evcp)/(system)/menu-access-dept/page.tsx
index dfda9172..25c27ada 100644
--- a/app/[lng]/evcp/(evcp)/(system)/menu-access-dept/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/menu-access-dept/page.tsx
@@ -3,8 +3,16 @@ import { Separator } from "@/components/ui/separator";
import { Shell } from "@/components/shell";
import { DepartmentMenuAccessManager } from "./_components/department-menu-access-manager";
import { getAllDepartmentsTree, getCurrentCompanyInfo } from "@/lib/users/knox-service";
+import { useTranslation } from "@/i18n";
+
+interface menuAccessDeptPageProps {
+ params: Promise<{ lng: string }>
+}
+
+export default async function DepartmentMenuAccessPage({ params }: menuAccessDeptPageProps) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
-export default async function DepartmentMenuAccessPage() {
// Promise들을 생성하여 클라이언트 컴포넌트에 전달
const departmentsPromise = getAllDepartmentsTree();
const companyInfo = await getCurrentCompanyInfo();
@@ -14,11 +22,13 @@ export default async function DepartmentMenuAccessPage() {
<div className="space-y-6">
{/* 헤더 섹션 */}
<div className="space-y-2">
- <h1 className="text-2xl font-bold tracking-tight">부서별 메뉴 접근권한 관리</h1>
- <p className="text-muted-foreground">
- Knox 조직도를 기반으로 부서별 도메인을 할당하여 메뉴 접근 권한을 관리할 수 있습니다.
- 상위 부서를 선택하면 하위 부서들도 자동으로 포함됩니다.
- </p>
+ <h1 className="text-2xl font-bold tracking-tight">
+ {t('menu.information_system.menu_access_dept')}
+ </h1>
+ {/* <p className="text-muted-foreground"> */}
+ {/* Knox 조직도를 기반으로 부서별 도메인을 할당하여 메뉴 접근 권한을 관리할 수 있습니다. */}
+ {/* 상위 부서를 선택하면 하위 부서들도 자동으로 포함됩니다. */}
+ {/* </p> */}
</div>
<Separator />
diff --git a/app/[lng]/evcp/(evcp)/(system)/menu-access/page.tsx b/app/[lng]/evcp/(evcp)/(system)/menu-access/page.tsx
index 7f5228df..4fa712f1 100644
--- a/app/[lng]/evcp/(evcp)/(system)/menu-access/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/menu-access/page.tsx
@@ -8,11 +8,15 @@ import { searchParamsUsersCache } from "@/lib/admin-users/validations"
import { getUsersNotPartners } from "@/lib/users/service";
import { UserAccessControlTable } from "@/lib/users/access-control/users-table";
import { InformationButton } from "@/components/information/information-button";
+import { useTranslation } from "@/i18n";
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>;
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams;
const search = searchParamsUsersCache.parse(searchParams);
const validFilters = getValidFilters(search.filters);
@@ -29,7 +33,9 @@ export default async function IndexPage(props: IndexPageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">메뉴 접근제어 관리</h2>
+ <h2 className="text-2xl font-bold tracking-tight">
+ {t('menu.information_system.menu_access')}
+ </h2>
<InformationButton pagePath="evcp/menu-access" />
</div>
{/* <p className="text-muted-foreground">
@@ -53,4 +59,4 @@ export default async function IndexPage(props: IndexPageProps) {
</React.Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/menu-list/page.tsx b/app/[lng]/evcp/(evcp)/(system)/menu-list/page.tsx
index 5a1f71a5..79923397 100644
--- a/app/[lng]/evcp/(evcp)/(system)/menu-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/menu-list/page.tsx
@@ -1,91 +1,20 @@
-// app/evcp/menu-list/page.tsx
+import { MenuTreeManager } from "@/lib/menu-v2/components/menu-tree-manager";
-import { Suspense } from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { RefreshCw, Settings } from "lucide-react";
-import { getActiveUsers, getMenuAssignments } from "@/lib/menu-list/servcie";
-import { InitializeButton } from "@/lib/menu-list/table/initialize-button";
-import { MenuListTable } from "@/lib/menu-list/table/menu-list-table";
-import { Shell } from "@/components/shell"
-import * as React from "react"
-import { InformationButton } from "@/components/information/information-button";
-import { useTranslation } from "@/i18n";
-interface MenuListPageProps {
- params: Promise<{ lng: string }>
+interface PageProps {
+ params: Promise<{ lng: string }>;
}
-export default async function MenuListPage({ params }: MenuListPageProps) {
- const { lng } = await params
- const { t } = await useTranslation(lng, 'menu')
+export default async function MenuV2Page({ params }: PageProps) {
+ const { lng } = await params;
- // 초기 데이터 로드
- const [menusResult, usersResult] = await Promise.all([
- getMenuAssignments(),
- getActiveUsers()
- ]);
-
- // 서버사이드에서 번역된 메뉴 데이터 생성
- const translatedMenus = menusResult.data?.map(menu => ({
- ...menu,
- sectionTitle: menu.sectionTitle || "",
- translatedMenuTitle: t(menu.menuTitle || ""),
- translatedSectionTitle: t(menu.sectionTitle || ""),
- translatedMenuGroup: menu.menuGroup ? t(menu.menuGroup) : null,
- translatedMenuDescription: menu.menuDescription ? t(menu.menuDescription) : null
- })) || [];
-
return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">
- 메뉴 관리
- </h2>
- <InformationButton pagePath="evcp/menu-list" />
- </div>
- {/* <p className="text-muted-foreground">
- 각 메뉴별로 담당자를 지정하고 관리할 수 있습니다.
- </p> */}
- </div>
- </div>
-
+ <div className="container mx-auto py-6 space-y-6">
+ <div>
+ <h1 className="text-2xl font-bold tracking-tight">Menu Management</h1>
</div>
-
-
- <React.Suspense
- fallback={
- ""
- }
- >
- <Card>
- <CardHeader>
- <CardTitle className="flex items-center gap-2">
- <Settings className="h-5 w-5" />
- 메뉴 리스트
- </CardTitle>
- <CardDescription>
- 시스템의 모든 메뉴와 담당자 정보를 확인할 수 있습니다.
- {menusResult.data?.length > 0 && (
- <span className="ml-2 text-sm">
- 총 {menusResult.data.length}개의 메뉴
- </span>
- )}
- </CardDescription>
- </CardHeader>
- <CardContent>
- <Suspense fallback={<div className="text-center py-8">로딩 중...</div>}>
- <MenuListTable
- initialMenus={translatedMenus}
- initialUsers={usersResult.data || []}
- />
- </Suspense>
- </CardContent>
- </Card>
- </React.Suspense>
- </Shell>
-
+
+ <MenuTreeManager initialDomain="evcp" />
+ </div>
);
-} \ No newline at end of file
+}
+
diff --git a/app/[lng]/evcp/(evcp)/(system)/notice/page.tsx b/app/[lng]/evcp/(evcp)/(system)/notice/page.tsx
index a4157d1b..ab01edfa 100644
--- a/app/[lng]/evcp/(evcp)/(system)/notice/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/notice/page.tsx
@@ -7,13 +7,21 @@ import { NoticeClient } from "@/components/notice/notice-client"
import { InformationButton } from "@/components/information/information-button"
import { getNoticeLists } from "@/lib/notice/service"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "공지사항 관리",
description: "페이지별 공지사항을 관리합니다.",
}
-export default async function NoticePage() {
+interface noticePageProps {
+ params: Promise<{ lng: string }>
+}
+
+export default async function NoticePage({ params }: noticePageProps) {
+ const { lng } = await params
+ const { t } = await useTranslation(lng, 'menu')
+
noStore()
// 세션에서 사용자 ID 가져오기
@@ -47,7 +55,7 @@ export default async function NoticePage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 공지사항 관리
+ {t('menu.information_system.notice')}
</h2>
<InformationButton pagePath="evcp/notice" />
</div>
@@ -57,4 +65,4 @@ export default async function NoticePage() {
<NoticeClient initialData={initialData?.data || []} currentUserId={currentUserId} />
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/(system)/page-visits/page.tsx b/app/[lng]/evcp/(evcp)/(system)/page-visits/page.tsx
index 07275cad..6b8e4a2a 100644
--- a/app/[lng]/evcp/(evcp)/(system)/page-visits/page.tsx
+++ b/app/[lng]/evcp/(evcp)/(system)/page-visits/page.tsx
@@ -8,12 +8,16 @@ import { Shell } from "@/components/shell"
import { getPageVisits } from "@/lib/page-visits/service"
import { searchParamsCache } from "@/lib/page-visits/validation"
import { PageVisitsTable } from "@/lib/page-visits/table/page-visits-table"
+import { useTranslation } from "@/i18n"
interface PageVisitsPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function PageVisitsPage(props: PageVisitsPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = searchParamsCache.parse(searchParams)
@@ -33,7 +37,7 @@ export default async function PageVisitsPage(props: PageVisitsPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 페이지 방문 이력
+ {t('menu.information_system.page_visits')}
</h2>
</div>
{/* <p className="text-muted-foreground">
@@ -58,4 +62,4 @@ export default async function PageVisitsPage(props: PageVisitsPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/evcp/(evcp)/edp-progress/page.tsx b/app/[lng]/evcp/(evcp)/edp-progress/page.tsx
index fe040709..b205dd77 100644
--- a/app/[lng]/evcp/(evcp)/edp-progress/page.tsx
+++ b/app/[lng]/evcp/(evcp)/edp-progress/page.tsx
@@ -4,15 +4,21 @@ import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { Shell } from "@/components/shell"
import { InformationButton } from "@/components/information/information-button"
import { VendorFormStatusTable } from "@/components/form-data-stat/form-data-stat-table"
+import { useTranslation } from "@/i18n"
+interface edpProgressPageProps {
+ params: Promise<{ lng: string }>
+}
-export default async function IndexPage() {
+export default async function IndexPage(props: edpProgressPageProps) {
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
return (
<Shell className="gap-2">
<div className="flex items-center justify-between space-y-2">
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">벤더 데이터 진척도 현황</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.engineering_management.vendor_progress')}</h2>
<InformationButton pagePath="evcp/edp-progress" />
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/layout.tsx b/app/[lng]/evcp/(evcp)/layout.tsx
index 7fe7f3e7..093d9301 100644
--- a/app/[lng]/evcp/(evcp)/layout.tsx
+++ b/app/[lng]/evcp/(evcp)/layout.tsx
@@ -1,5 +1,5 @@
import { ReactNode } from 'react';
-import { Header } from '@/components/layout/Header';
+import { HeaderV2 } from '@/components/layout/HeaderV2';
import { SiteFooter } from '@/components/layout/Footer';
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
@@ -12,12 +12,16 @@ export default async function EvcpLayout({ children }: { children: ReactNode })
let isAuthorized = true;
let authMessage = "";
- // Only check permission if user is logged in
- if (session?.user?.id) {
+ // Skip permission check if environment variable is set
+ const skipPermissionCheck = process.env.SKIP_ORACLE_PERMISSION_CHECK === 'true';
+
+ // Only check permission if user is logged in and check is not skipped
+ if (session?.user?.id && !skipPermissionCheck) {
try {
const result = await verifyNonsapPermission(
parseInt(session.user.id),
- ['SEARCH']
+ // ['SEARCH']
+ [] // 아무런 실제 권한이 없어도, 등록된 상태라면 화면에 'SEARCH' 권한이 있는것처럼 동작하게 해달라고 함. (김희은 프로)
);
isAuthorized = result.authorized;
authMessage = result.message || "";
@@ -33,8 +37,10 @@ export default async function EvcpLayout({ children }: { children: ReactNode })
return (
<div className="relative flex min-h-svh flex-col bg-background">
{/* <div className="relative flex min-h-svh flex-col bg-slate-100 "> */}
- <Header />
- <PermissionChecker authorized={isAuthorized} message={authMessage} />
+ <HeaderV2 />
+ {!skipPermissionCheck && (
+ <PermissionChecker authorized={isAuthorized} message={authMessage} />
+ )}
<main className="flex flex-1 flex-col">
<div className='container-wrapper'>
{children}
diff --git a/app/[lng]/partners/(partners)/basic-contract/page.tsx b/app/[lng]/partners/(partners)/basic-contract/page.tsx
index e2213c57..c651ee54 100644
--- a/app/[lng]/partners/(partners)/basic-contract/page.tsx
+++ b/app/[lng]/partners/(partners)/basic-contract/page.tsx
@@ -11,13 +11,15 @@ import { BasicContractsVendorTable } from "@/lib/basic-contract/vendor-table/bas
import { getServerSession } from "next-auth"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
-
-
+ const { lng } = await props.params;
+ const { t } = await useTranslation(lng, 'menu')
const session = await getServerSession(authOptions)
const vendorId = session?.user.companyId
@@ -43,7 +45,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 기본계약서 서명 요청
+ {t('menu.vendor.procurement.basic_contract_sign')}
</h2>
<InformationButton pagePath="partners/basic-contract" />
</div>
@@ -77,4 +79,4 @@ export default async function IndexPage(props: IndexPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/bid/page.tsx b/app/[lng]/partners/(partners)/bid/page.tsx
index a09dec72..87b52021 100644
--- a/app/[lng]/partners/(partners)/bid/page.tsx
+++ b/app/[lng]/partners/(partners)/bid/page.tsx
@@ -5,8 +5,15 @@ import { authOptions } from "@/app/api/auth/[...nextauth]/route"
import { getBiddingListForPartners } from '@/lib/bidding/detail/service'
import { Shell } from '@/components/shell'
import { DataTableSkeleton } from '@/components/data-table/data-table-skeleton'
+import { useTranslation } from "@/i18n"
-export default async function PartnersBidPage() {
+interface IndexPageProps {
+ params: Promise<{ lng: string }>
+}
+
+export default async function PartnersBidPage({ params }: IndexPageProps) {
+ const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
// 세션에서 companyId 가져오기
const session = await getServerSession(authOptions)
const companyId = session?.user?.companyId
@@ -31,9 +38,9 @@ export default async function PartnersBidPage() {
<div className="container mx-auto py-6 space-y-6">
<div className="flex items-center justify-between">
<div>
- <h1 className="text-3xl font-bold">입찰 참여</h1>
+ <h1 className="text-3xl font-bold">{t('menu.vendor.bidding.list')}</h1>
<p className="text-muted-foreground mt-2">
- 참여 가능한 입찰 목록을 확인하고 응찰하실 수 있습니다.
+ {t('menu.vendor.bidding.list_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/document-list-ship/page.tsx b/app/[lng]/partners/(partners)/document-list-ship/page.tsx
index 46800a77..d67e96df 100644
--- a/app/[lng]/partners/(partners)/document-list-ship/page.tsx
+++ b/app/[lng]/partners/(partners)/document-list-ship/page.tsx
@@ -3,6 +3,7 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import DolceUploadPageV2 from "./dolce-upload-page-v2";
import { Shell } from "@/components/shell";
+import { useTranslation } from "@/i18n"
// ============================================================================
// 로딩 스켈레톤
@@ -39,6 +40,7 @@ export default async function DolceUploadPageWrapper({
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
const resolvedParams = await searchParams;
return (
@@ -47,9 +49,7 @@ export default async function DolceUploadPageWrapper({
<div className="flex items-center justify-between flex-shrink-0">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- {lng === "ko"
- ? "조선 도면 업로드"
- : "Shipbuilding Drawing Upload"}
+ {t('menu.vendor.engineering.document_list_ship')}
</h2>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/evaluation/page.tsx b/app/[lng]/partners/(partners)/evaluation/page.tsx
index be88ef3e..3680a826 100644
--- a/app/[lng]/partners/(partners)/evaluation/page.tsx
+++ b/app/[lng]/partners/(partners)/evaluation/page.tsx
@@ -13,11 +13,15 @@ import { getEvaluationSubmissions } from "@/lib/vendor-evaluation-submit/service
import { getEvaluationsSubmitSchema } from "@/lib/vendor-evaluation-submit/validation"
import { EvaluationSubmissionsTable } from "@/lib/vendor-evaluation-submit/table/submit-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params;
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = getEvaluationsSubmitSchema.parse(searchParams)
const validFilters = getValidFilters(search.filters)
@@ -34,7 +38,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 평가자료 입력
+ {t('menu.vendor.procurement.evaluation_input')}
</h2>
<InformationButton pagePath="partners/evaluation" />
</div>
@@ -105,7 +109,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div className="flex items-center justify-between space-y-2">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 평가자료 입력
+ {t('menu.vendor.procurement.evaluation_input')}
</h2>
{/* <p className="text-muted-foreground">
요청된 정기평가를 입력하고 제출할 수 있습니다.
@@ -133,4 +137,4 @@ export default async function IndexPage(props: IndexPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/general-contract-review/page.tsx b/app/[lng]/partners/(partners)/general-contract-review/page.tsx
index 27afd859..5af40906 100644
--- a/app/[lng]/partners/(partners)/general-contract-review/page.tsx
+++ b/app/[lng]/partners/(partners)/general-contract-review/page.tsx
@@ -6,10 +6,16 @@ import { getVendorContractReviews } from "@/lib/general-contracts/service"
import { VendorGeneralContractReviewTable } from "./vendor-general-contract-review-table"
import { InformationButton } from "@/components/information/information-button"
import { unstable_noStore as noStore } from 'next/cache'
+import { useTranslation } from "@/i18n"
-export default async function VendorGeneralContractReviewPage() {
+interface pageProps {
+ params: { lng: string }
+}
+
+export default async function VendorGeneralContractReviewPage({ params }: pageProps) {
noStore()
-
+ const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
const session = await getServerSession(authOptions)
if (!session?.user?.companyId) {
@@ -31,12 +37,12 @@ export default async function VendorGeneralContractReviewPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 일반계약 조건검토
+ {t('menu.vendor.procurement.general_contract_review')}
</h2>
<InformationButton pagePath="partners/general-contract-review" />
</div>
<p className="text-muted-foreground">
- 조건검토 요청된 계약 목록을 확인하고 검토합니다.
+ {t('menu.vendor.procurement.general_contract_review_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/layout.tsx b/app/[lng]/partners/(partners)/layout.tsx
index 9dc39f7b..51a30028 100644
--- a/app/[lng]/partners/(partners)/layout.tsx
+++ b/app/[lng]/partners/(partners)/layout.tsx
@@ -1,11 +1,11 @@
import { ReactNode } from 'react';
-import { Header } from '@/components/layout/Header';
+import { HeaderV2 } from '@/components/layout/HeaderV2';
import { SiteFooter } from '@/components/layout/Footer';
export default function EvcpLayout({ children }: { children: ReactNode }) {
return (
<div className="relative flex min-h-svh flex-col bg-background">
- <Header />
+ <HeaderV2 />
<main className="flex flex-1 flex-col">
<div className='container-wrapper'>
{children}
diff --git a/app/[lng]/partners/(partners)/pcr/page.tsx b/app/[lng]/partners/(partners)/pcr/page.tsx
index dc639aa8..7148aedd 100644
--- a/app/[lng]/partners/(partners)/pcr/page.tsx
+++ b/app/[lng]/partners/(partners)/pcr/page.tsx
@@ -5,7 +5,7 @@ import { redirect } from "next/navigation";
import { Shell } from "@/components/shell"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { InformationButton } from "@/components/information/information-button"
-
+import { useTranslation } from "@/i18n"
import { PcrTable } from "@/lib/pcr/table/pcr-table";
import { getPcrPoListForPartners } from "@/lib/pcr/service";
@@ -14,6 +14,10 @@ export const metadata = {
description: "Purchase Change Request를 조회하고 관리할 수 있습니다.",
};
+interface pageProps {
+ params: { lng: string }
+}
+
async function PartnersPcrTableWrapper() {
// 세션에서 사용자 정보 확인
const session = await getServerSession(authOptions);
@@ -33,7 +37,9 @@ async function PartnersPcrTableWrapper() {
return <PcrTable tableData={tableData} isEvcpPage={false} isPartnersPage={true} currentVendorId={vendorId} />;
}
-export default function PartnersPcrPage() {
+export default async function PartnersPcrPage({ params }: pageProps) {
+ const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
return (
<Shell className="gap-4">
{/* ═══════════════════════════════════════════════════════════════ */}
@@ -44,12 +50,12 @@ export default function PartnersPcrPage() {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- PCR 관리
+ {t('menu.vendor.procurement.pcr')}
</h2>
<InformationButton pagePath="partners/pcr" />
</div>
<p className="text-muted-foreground">
- Purchase Change Request를 조회하고 관리할 수 있습니다. PCR 승인 상태, 변경 구분, PO/계약 정보 등을 확인할 수 있습니다.
+ {t('menu.vendor.procurement.pcr_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/po/page.tsx b/app/[lng]/partners/(partners)/po/page.tsx
index 709b975c..a2ab2916 100644
--- a/app/[lng]/partners/(partners)/po/page.tsx
+++ b/app/[lng]/partners/(partners)/po/page.tsx
@@ -11,12 +11,16 @@ import { getVendorPOs } from "@/lib/po/vendor-table/service"
import { vendorPoSearchParamsCache } from "@/lib/po/vendor-table/validations"
import { VendorPoTable } from "@/lib/po/vendor-table/vendor-po-table"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
interface VendorPOPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function VendorPO(props: VendorPOPageProps) {
+ const { lng } = await props.params;
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = vendorPoSearchParamsCache.parse(searchParams)
@@ -47,7 +51,7 @@ export default async function VendorPO(props: VendorPOPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- PO/계약 목록
+ {t('menu.vendor.procurement.po')}
</h2>
<InformationButton pagePath="partners/po" />
</div>
@@ -72,4 +76,4 @@ export default async function VendorPO(props: VendorPOPageProps) {
</React.Suspense>
</Shell>
)
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/pq_new/page.tsx b/app/[lng]/partners/(partners)/pq_new/page.tsx
index eea5b21d..fb77ce0e 100644
--- a/app/[lng]/partners/(partners)/pq_new/page.tsx
+++ b/app/[lng]/partners/(partners)/pq_new/page.tsx
@@ -25,6 +25,11 @@ import {
DropdownMenuContent,
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";
+import { useTranslation } from "@/i18n"
+
+interface IndexPageProps {
+ params: Promise<{ lng: string }>
+}
export const metadata: Metadata = {
title: "사전 평가 (PQ) 목록",
@@ -60,10 +65,11 @@ function getFormattedDate(date: Date | null) {
}).format(new Date(date));
}
-export default async function PQListPage() {
+export default async function PQListPage({ params }: IndexPageProps) {
// 캐시 비활성화
noStore();
-
+ const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
// 인증 확인
const session = await getServerSession(authOptions);
@@ -74,10 +80,10 @@ export default async function PQListPage() {
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- 사전 평가 (PQ) 목록
+ {t('menu.vendor.procurement.pq_new')}
</h2>
<p className="text-muted-foreground">
- 요청된 사전 평가 목록을 확인하고 작성합니다.
+ {t('menu.vendor.procurement.pq_new_desc')}
</p>
</div>
</div>
@@ -139,11 +145,13 @@ export default async function PQListPage() {
<div className="flex justify-between items-center">
<div>
<div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">사전 평가 (PQ) 목록</h2>
+ <h2 className="text-2xl font-bold tracking-tight">
+ {t('menu.vendor.procurement.pq_new')}
+ </h2>
<InformationButton pagePath="partners/pq_new" />
</div>
<p className="text-muted-foreground">
- 요청된 사전 평가 목록을 확인하고 작성합니다.
+ {t('menu.vendor.procurement.pq_new_desc')}
</p>
</div>
</div>
@@ -295,4 +303,4 @@ export default async function PQListPage() {
</Card>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/rfq-last/page.tsx b/app/[lng]/partners/(partners)/rfq-last/page.tsx
index a49ed648..5a64d4b2 100644
--- a/app/[lng]/partners/(partners)/rfq-last/page.tsx
+++ b/app/[lng]/partners/(partners)/rfq-last/page.tsx
@@ -15,6 +15,7 @@ import { searchParamsVendorRfqCache } from "@/lib/rfq-last/vendor-response/valid
import { InformationButton } from "@/components/information/information-button"
import { getVendorQuotationsLast,getQuotationStatusCountsLast } from "@/lib/rfq-last/vendor-response/service";
import { VendorQuotationsTableLast } from "@/lib/rfq-last/vendor-response/vendor-quotations-table";
+import { useTranslation } from "@/i18n"
export const metadata: Metadata = {
title: "견적 목록",
@@ -22,11 +23,14 @@ export const metadata: Metadata = {
};
interface IndexPageProps {
+ params: Promise<{ lng: string }>
searchParams: Promise<SearchParams>
}
export default async function IndexPage(props: IndexPageProps) {
+ const { lng } = await props.params;
+ const { t } = await useTranslation(lng, 'menu')
const searchParams = await props.searchParams
const search = searchParamsVendorRfqCache.parse(searchParams)
const validFilters = getValidFilters(search.filters)
@@ -41,7 +45,7 @@ export default async function IndexPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- 견적 목록
+ {t('menu.vendor.procurement.rfq_response')}
</h2>
<InformationButton pagePath="partners/rfq-last" />
</div>
@@ -112,9 +116,9 @@ export default async function IndexPage(props: IndexPageProps) {
<Shell className="gap-6">
<div className="flex justify-between items-center">
<div>
- <h2 className="text-2xl font-bold tracking-tight">견적 목록</h2>
+ <h2 className="text-2xl font-bold tracking-tight">{t('menu.vendor.procurement.rfq_response')}</h2>
<p className="text-muted-foreground">
- 진행 중인 견적서 목록을 확인하고 관리합니다.
+ {t('menu.vendor.procurement.rfq_response_desc')}
</p>
</div>
</div>
@@ -190,4 +194,4 @@ export default async function IndexPage(props: IndexPageProps) {
</React.Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/swp-document-upload/page.tsx b/app/[lng]/partners/(partners)/swp-document-upload/page.tsx
index b97bc7fc..55073062 100644
--- a/app/[lng]/partners/(partners)/swp-document-upload/page.tsx
+++ b/app/[lng]/partners/(partners)/swp-document-upload/page.tsx
@@ -3,6 +3,7 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import VendorDocumentPage from "./vendor-document-page";
import { Shell } from "@/components/shell";
+import { useTranslation } from "@/i18n"
export const metadata = {
title: "Document Search and Upload",
@@ -31,11 +32,15 @@ function VendorDocumentSkeleton() {
}
export default async function DocumentUploadPage({
+ params,
searchParams,
}: {
+ params: Promise<{ lng: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
- const params = await searchParams;
+ const { lng } = await params;
+ const { t } = await useTranslation(lng, 'menu')
+ const resolvedParams = await searchParams;
return (
<Shell>
@@ -43,15 +48,15 @@ export default async function DocumentUploadPage({
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- SWP Document Submission
+ {t('menu.vendor.engineering.document_submission')}
</h2>
</div>
</div>
{/* 메인 컨텐츠 */}
<Suspense fallback={<VendorDocumentSkeleton />}>
- <VendorDocumentPage searchParams={params} />
+ <VendorDocumentPage searchParams={resolvedParams} />
</Suspense>
</Shell>
);
-} \ No newline at end of file
+}
diff --git a/app/[lng]/partners/(partners)/tbe-last/page.tsx b/app/[lng]/partners/(partners)/tbe-last/page.tsx
index 62a982c7..c8da944a 100644
--- a/app/[lng]/partners/(partners)/tbe-last/page.tsx
+++ b/app/[lng]/partners/(partners)/tbe-last/page.tsx
@@ -10,6 +10,8 @@ import { Skeleton } from "@/components/ui/skeleton"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { Shell } from "@/components/shell"
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n"
+
interface IndexPageProps {
// Next.js 13 App Router에서 기본으로 주어지는 객체들
params: {
@@ -20,8 +22,8 @@ interface IndexPageProps {
}
export default async function RfqTBEPage(props: IndexPageProps) {
- const resolvedParams = await props.params
- const lng = resolvedParams.lng
+ const { lng } = await props.params
+ const { t } = await useTranslation(lng, 'menu')
// 2) SearchParams 파싱 (Zod)
// - "filters", "page", "perPage", "sort" 등 contact 전용 컬럼
@@ -51,7 +53,7 @@ export default async function RfqTBEPage(props: IndexPageProps) {
<div>
<div className="flex items-center gap-2">
<h2 className="text-2xl font-bold tracking-tight">
- TBE 관리
+ {t('menu.vendor.engineering.tbe')}
</h2>
<InformationButton pagePath="partners/tbe" />
</div>
diff --git a/app/[lng]/partners/(partners)/techsales/rfq-offshore-hull/page.tsx b/app/[lng]/partners/(partners)/techsales/rfq-offshore-hull/page.tsx
index ee31c95b..1254e992 100644
--- a/app/[lng]/partners/(partners)/techsales/rfq-offshore-hull/page.tsx
+++ b/app/[lng]/partners/(partners)/techsales/rfq-offshore-hull/page.tsx
@@ -8,12 +8,16 @@ import { LogIn } from "lucide-react";
import { Shell } from "@/components/shell";
import { VendorQuotationsTable } from "@/lib/techsales-rfq/vendor-response/table/vendor-quotations-table";
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n";
+
export const metadata: Metadata = {
title: "기술영업 해양HULL RFQ 관리",
description: "기술영업 해양HULL RFQ를 관리합니다.",
};
-export default async function VendorQuotationsHullPage() {
+export default async function VendorQuotationsHullPage(props: { params: { lng: string } }) {
+ const { lng } = props.params
+ const { t } = await useTranslation(lng, 'menu')
// 세션 확인
const session = await getServerSession(authOptions);
@@ -62,11 +66,11 @@ export default async function VendorQuotationsHullPage() {
<div className="flex-shrink-0 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<div className="flex items-center gap-2">
- <h1 className="text-2xl font-bold tracking-tight">기술영업 해양HULL RFQ</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.vendor.sales.offshore_hull_rfq')}</h1>
<InformationButton pagePath="partners/techsales/rfq-offshore-hull" />
</div>
<p className="text-muted-foreground">
- 할당받은 해양HULL RFQ에 대한 견적서를 작성하고 관리합니다.
+ {t('menu.vendor.sales.offshore_hull_rfq_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/techsales/rfq-offshore-top/page.tsx b/app/[lng]/partners/(partners)/techsales/rfq-offshore-top/page.tsx
index 36697a3f..467f2bdb 100644
--- a/app/[lng]/partners/(partners)/techsales/rfq-offshore-top/page.tsx
+++ b/app/[lng]/partners/(partners)/techsales/rfq-offshore-top/page.tsx
@@ -8,13 +8,17 @@ import { LogIn } from "lucide-react";
import { Shell } from "@/components/shell";
import { InformationButton } from "@/components/information/information-button"
import { VendorQuotationsTable } from "@/lib/techsales-rfq/vendor-response/table/vendor-quotations-table";
+import { useTranslation } from "@/i18n";
+
export const metadata: Metadata = {
title: "기술영업 해양TOP RFQ 관리",
description: "기술영업 해양TOP RFQ를 관리합니다.",
};
-export default async function VendorQuotationsTopPage() {
+export default async function VendorQuotationsTopPage(props: { params: { lng: string } }) {
+ const { lng } = props.params
+ const { t } = await useTranslation(lng, 'menu')
// 세션 확인
const session = await getServerSession(authOptions);
@@ -64,11 +68,11 @@ export default async function VendorQuotationsTopPage() {
<div className="flex-shrink-0 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<div className="flex items-center gap-2">
- <h1 className="text-2xl font-bold tracking-tight">기술영업 해양TOP RFQ</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.vendor.sales.offshore_top_rfq')}</h1>
<InformationButton pagePath="partners/techsales/rfq-offshore-top" />
</div>
<p className="text-muted-foreground">
- 할당받은 해양TOP RFQ에 대한 견적서를 작성하고 관리합니다.
+ {t('menu.vendor.sales.offshore_top_rfq_desc')}
</p>
</div>
</div>
diff --git a/app/[lng]/partners/(partners)/techsales/rfq-ship/page.tsx b/app/[lng]/partners/(partners)/techsales/rfq-ship/page.tsx
index bd3291f4..271d62c7 100644
--- a/app/[lng]/partners/(partners)/techsales/rfq-ship/page.tsx
+++ b/app/[lng]/partners/(partners)/techsales/rfq-ship/page.tsx
@@ -9,12 +9,17 @@ import { LogIn } from "lucide-react";
import { Shell } from "@/components/shell";
import { VendorQuotationsTable } from "@/lib/techsales-rfq/vendor-response/table/vendor-quotations-table";
import { InformationButton } from "@/components/information/information-button"
+import { useTranslation } from "@/i18n";
+
+
export const metadata: Metadata = {
title: "기술영업 조선 RFQ 관리",
description: "기술영업 조선 RFQ를 관리합니다.",
};
-export default async function VendorQuotationsPage() {
+export default async function VendorQuotationsPage(props: { params: { lng: string } }) {
+ const { lng } = props.params
+ const { t } = await useTranslation(lng, 'menu')
// 세션 확인
const session = await getServerSession(authOptions);
console.log(session, "session")
@@ -67,11 +72,11 @@ export default async function VendorQuotationsPage() {
<div className="flex-shrink-0 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<div className="flex items-center gap-2">
- <h1 className="text-2xl font-bold tracking-tight">기술영업 조선 RFQ</h1>
+ <h1 className="text-2xl font-bold tracking-tight">{t('menu.vendor.sales.ship_rfq')}</h1>
<InformationButton pagePath="partners/techsales/rfq-ship" />
</div>
<p className="text-muted-foreground">
- 할당받은 조선 RFQ에 대한 견적서를 작성하고 관리합니다.
+ {t('menu.vendor.sales.ship_rfq_desc')}
</p>
</div>
</div>